#!/usr/bin/env python
#coding=utf-8

import json
from pprint import pprint, pformat

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkslb.request.v20140515.TagResourcesRequest import TagResourcesRequest
from aliyunsdkslb.request.v20140515.UntagResourcesRequest import UntagResourcesRequest
from aliyunsdkslb.request.v20140515.DescribeLoadBalancersRequest import DescribeLoadBalancersRequest
from aliyunsdkslb.request.v20140515.DescribeVServerGroupAttributeRequest import DescribeVServerGroupAttributeRequest
from aliyunsdkslb.request.v20140515.DescribeVServerGroupsRequest import DescribeVServerGroupsRequest

import logging
import pandas as pd
from aliyun_client import AliYunClient
from devops_api import DevOpsApi
from welab_logging import logs
from aliyun_common import AliYunCommon


class AliyunSlbTag(object):
    def __init__(self):
        self.logger = logging.getLogger('welab.aliyun.slb')
        self.aliyun_client = AliYunClient()
        self.aliyun = self.aliyun_client.get_all_client()
        self.dev_ops_api = DevOpsApi()
        self.aliyun_common = AliYunCommon()


    def get_tag(self, slb):
        if "Tags" not in slb or "Tag" not in slb["Tags"]:
            return "p_common"

        for tag in slb["Tags"]["Tag"]:
            if tag["TagKey"] == "appname":
                return tag["TagValue"]

        # 默认
        return "p_common"


    def get_aliyun_slb_info(self, account):
        page_size = 100
        page_number = 1
        slbs_info = []

        while True:
            request = DescribeLoadBalancersRequest()
            request.set_accept_format('json')

            request.set_PageNumber(page_number)
            request.set_PageSize(page_size)

            try:
                response = account["client"].do_action_with_exception(request)
                response = json.loads(str(response, encoding='utf-8'))

                for slb in response["LoadBalancers"]["LoadBalancer"]:
                    tag = self.aliyun_common.get_tag(slb)
                    slb_info = {
                        "id": slb['LoadBalancerId'],
                        "name": slb["LoadBalancerName"],
                        "ip": slb["Address"],
                        "account": account["name"],
                        "tag": tag,
                        "pay_type": slb["PayType"],
                        "load_balancer_spec": slb.get("LoadBalancerSpec", "性能共享型"),
                        "status": slb['LoadBalancerStatus']
                    }

                    slbs_info.append(slb_info)

                if page_number * page_size >= response["TotalCount"]:
                    break
                else:
                    page_number += 1

            except Exception as e:
                self.logger.error("get_aliyun_slb_info error =>{}".format(e))

        return slbs_info


    def get_all_slb_info(self):
        slbs_info = []
        for account in self.aliyun:
            slb_info = self.get_aliyun_slb_info(account)
            if not slb_info:
                self.logger.error("get slb info failed =>{}".format(account["name"]))
                continue
            slbs_info.extend(slb_info)

        self.logger.info("get slb info success")
        return slbs_info


    def write_info_to_excel(self):
        slbs_info = self.get_all_slb_info()
        tag_departments = self.dev_ops_api.get_all_tag_department()
        tag_infos = {
            tag_department["tag_value"]: tag_department
            for tag_department in tag_departments["data"]["items"]
        }

        for slb_info in slbs_info:
            # 根据tag来获取部门信息
            if slb_info["tag"] == "p_common" or slb_info["tag"] not in tag_infos:
                slb_info["belong_department"] = "无"
                slb_info["maintain_department"] = "无"
                continue
            slb_info["belong_department"] = tag_infos[slb_info["tag"]]["belong_department"]
            slb_info["maintain_department"] = tag_infos[slb_info["tag"]]["maintain_department"]

            # 获取服务器价格
            # result, price = self.aliyun_common.get_price(slb_info["account"], slb_info["id"])
            # if not result:
            #     self.logger.error(f"{slb_info['id']} get price failed")
            #     slb_info["price"] = "无"
            #     continue
            # slb_info["price"] = price


        df = pd.DataFrame(slbs_info)
        df.to_excel(f"slb信息.xlsx", index=False)
        self.logger.info("write info to_excel success")


    def read_info_from_excel(self):
        slbs_info = []
        df = pd.read_excel('slb信息梳理.xlsx', "Sheet1")
        for i in df.index.values:
            row_data = df.loc[i].to_dict()
            slbs_info.append(row_data)

        self.logger.info("write info to_excel success")
        return slbs_info


    def remove_tag(self, account, slb_info):
        try:
            request = UntagResourcesRequest()
            request.set_accept_format('json')

            request.set_ResourceType("instance")
            request.set_ResourceIds([slb_info["id"]])
            request.set_Tags([
                {
                    "Key": "group",
                    "Value": slb_info["tag"]
                }
            ])

            response = account["client"].do_action_with_exception(request)
            self.logger.info("{}({}) remove tag {} OK".format(slb_info["name"], slb_info["id"], slb_info["tag"]))
        except Exception as e:
            self.logger.error("{}({}) remove tag {} error {}".format(slb_info["name"], slb_info["id"], slb_info["tag"], e))
            return False

        return True

    def update_tag(self, account, slb_info, tag):
        try:
            request = TagResourcesRequest()
            request.set_accept_format('json')

            request.set_ResourceType("instance")
            request.set_ResourceIds([slb_info["id"]])
            request.set_Tags([
                {
                    "Key": tag,
                    "Value": slb_info[tag]
                }
            ])

            response = account["client"].do_action_with_exception(request)
            self.logger.info(f"{slb_info['name']}({slb_info['id']}) add tag {slb_info[tag]} ok")
        except Exception as e:
            self.logger.error(f"{slb_info['name']}({slb_info['id']}) add tag {slb_info[tag]} error {e}")
            return False
        return True


    def update_tag_from_excel(self):
        slbs_info = self.read_info_from_excel()
        for slb in slbs_info:
            client = self.aliyun_client.get_one_client(slb["account"])
            if not client:
                self.logger.warning("get aliyun client {slb['account']} failed")
                continue
            self.update_tag(client, slb, "appname")


    def check_all_slb_info(self):
        """
        检查所有的eip
        """
        slbs_info = self.get_all_slb_info()

        # 检查eip有没打标签
        for slb in slbs_info:
            if slb["tag"] == "p_common":
                self.logger.error("{} => {}:{} not tag".format(slb["account"], slb["name"], slb["ip"]))
        self.logger.info("check slb tag complete")




@logs()
def main():

    aliyun_slb = AliyunSlbTag()
    # aliyun_slb.check_all_slb_info()
    # aliyun_slb.get_all_slb_info()
    aliyun_slb.write_info_to_excel()
    # aliyun_slb.read_info_from_excel()
    # aliyun_slb.update_tag_from_excel()


if __name__ == "__main__":
    main()